#include "PacketHexBase.h"
#include "crc16.h"
#include <string.h>
#include "lib.h"

using namespace controller;

PacketHexBase::PacketHexBase() {}
PacketHexBase::~PacketHexBase() {}

PacketBase *PacketHexBase::on_get(char *pdata, int size, void *arg)
{
    unsigned char *d = (unsigned char *)&p;
    for (int i = 0; i < size; i++)
    {
        unsigned char data = (unsigned char)pdata[i];
        if (h.len > PacketBase::BUFFER_MAX)
            goto DECODE_ERROR;
        d[h.len] = data;
        h.len++;
        switch (h.state)
        {
        case 0:
            if (data == 0xAB)
            {
                h.state++;
                break;
            }
            else
                goto DECODE_ERROR;
        case 1:
            if (data == 0xBA)
            {
                h.state++;
                break;
            }
            else
                goto DECODE_ERROR;
        // hlen
        case 2:
            h.recv_len = p.hlen;
            h.recv_len <<= 8;
            h.state++;
            break;
            // llen
        case 3:
            h.recv_len += data;
            h.state++;
            break;
        // 接收数据
        case 4:
        {
            if (h.len < (h.recv_len + 4))
                break;
            else
            {
                uint16_t c = d[h.len - 2];
                c <<= 8;
                c |= d[h.len - 1];
                if (crc16(d + 2, h.len - 4) == c)
                {
                    // 接收到一个数据包
                    if (h.len <= 25)
                        h.user_size = 0;
                    else
                        h.user_size = h.len - 25;
                    h.framelen = h.len;
                    h.len = 0;
                    h.state = 0;
                    h.user_data = (char *)(d + 23);
                    // 大小端变换
                    // big_little((U8*)&h.p,(U8*)_packet_reverse,sizeof(_packet_reverse));
                    return this;
                }
                else
                    goto DECODE_ERROR;
            }
        }
        default:
            goto DECODE_ERROR;
        }
        continue;
    DECODE_ERROR:

        printf("PacketHexBase,error:%02X", data); // 数据异常，转发下一级
        // 本机芯处理
        if (data == 0xAB)
        {
            h.len = 1;
            h.state = 1;
            continue;
        }
        h.recv_len = h.len = h.state = 0;
        continue;
    }
    return NULL;
}
int PacketHexBase::to_bytes(char *dataout, void **arg)
{
    *arg = NULL;
    if (h.send_size > 0)
    {
        memcpy(dataout, (const void *)&p, h.send_size);
        return h.send_size;
    }
    return 0;
}
std::string PacketHexBase::to_string(std::string arg)
{
    return "未支持解析";
}
void PacketHexBase::reset_recv()
{
    h.reset();
}

int PacketHexBase::build(uint32_t d1, uint64_t d2, uint32_t t, uint8_t addr, uint16_t cmd, uint16_t datalen, uint8_t *data)
{
    uint8_t *d = (uint8_t *)&this->p;
    uint16_t crc = 0;
    if ((datalen + 25) >= PacketBase::BUFFER_MAX)
        datalen = PacketBase::BUFFER_MAX - 25;
    p.AB = 0xAB;
    p.BA = 0xBA;
    p.D1 = d1;
    p.D2 = d2;
    p.addr = addr;
    p.cmd = cmd;
    p.t = t;
    p.hlen = (21 + datalen) >> 8;
    p.llen = (21 + datalen) & 0xFF;
    if (datalen > 0 && p.data != data)
        memcpy(p.data, data, datalen);
    h.user_size = datalen;

    // 大小端变换
    LIB::big_little(d, (uint8_t *)_packet_reverse, sizeof(_packet_reverse));

    crc = crc16(d + 2, datalen + 21);
    p.data[datalen] = crc >> 8;
    p.data[datalen + 1] = 0xFF & crc;
    h.send_size = datalen + 25;
    return datalen + 25;
}
